from object import *

def testNative(thread):
  print 'ASDF!'
  thread.terminate(value=['literal', 'b'])

def testNative2(thread):
  print thread.symc['x']
  thread.terminate(value=['literal', 'b'])

def arbre_print(thread):
  from termcolor import colored
  s=thread.receiver
  if s.__class__==ArbrePrimitiveObject:
    print colored(s.value, 'green')
  else:
    print colored(str(s), 'blue')
  thread.terminate()

def arbre_printIt(thread):
  from termcolor import colored
  print 'printIt args:', thread.args, thread.active
  s=thread.active.get('s')
  print 'printIt:', s, type(s), s.__class__
  if s.__class__==ArbrePrimitiveObject:
    print colored(s.value, 'green')
  else:
    print colored(str(s), 'blue')
  thread.terminate()

def add(thread):
  b=thread.receiver.value
  a=thread.active.get('a').value
  thread.terminate(value=primitive(thread.active, 'result', b+a))

def subtract(thread):
  b=thread.receiver.value
  a=thread.active.get('a').value
  thread.terminate(value=primitive(thread.active, 'result', b-a))

def multiply(thread):
  b=thread.receiver.value
  a=thread.active.get('a').value
  thread.terminate(value=primitive(thread.active, 'result', b*a))

def divide(thread):
  b=thread.receiver.value
  a=thread.active.get('a').value
  thread.terminate(value=primitive(thread.active, 'result', b/a))

def arbre_and(thread):
  a=thread.symc['a'][1]
  b=thread.symc['b'][1]
  thread.terminate(value=['literal', a and b])

def arbre_or(thread):
  a=thread.symc['a'][1]
  b=thread.symc['b'][1]
  thread.terminate(value=['literal', a or b])

def lt(thread):
  print 'lt', thread.active, thread.active.method.obj
  b=thread.receiver.value
  a=thread.active.get('a').value
  print 'lt', a, b, a<b
  thread.terminate(value=primitive(thread.active, 'result', b<a))

def gt(thread):
  print 'gt', thread.active, thread.active.method.obj
  b=thread.receiver.value
  a=thread.active.get('a').value
  print 'gt', a, b, a>b
  thread.terminate(value=primitive(thread.active, 'result', b>a))

def eq(thread):
  print 'eq', thread.active, thread.active.method.obj
  b=thread.receiver.value
  a=thread.active.get('a').value
  print 'eq', a, b, a==b
  thread.terminate(value=primitive(thread.active, 'result', a==b))

def set(thread):
  var=thread.symc['var'][1]
  value=thread.symc['value']
  #print '!!! setting', var, 'to', value
  #thread.symc[var]=value
  #print 'changed thread.symc:', thread.symc
  thread.terminate(value=["literal", {var: value}])

def also(thread):
  from arbre import Reference
  from trees import MagicList

  f=thread.symc['a']
  ftype=f[0]
  if ftype!='block':
    print 'type error, also arg not block'
    return
  fdefc=f[1]
  #print 'fdefc:', fdefc, fdefc
  fcallc=thread.symc
  fblockc=blockc
  fargs=fdefc['args']
  fep=fdefc['code']
  #print 'also adding thread a ', fargs, fep
  ta=thread.sched.addThread(fdefc, fcallc, fblockc, fargs, fep)

  f=thread.symc['b']
  ftype=f[0]
  if ftype!='block':
    print 'type error, also arg not block'
    return
  fdefc=f[1]
  fcallc=thread.symc
  fblockc=blockc
  fargs=fdefc['args']
  fep=fdefc['code']
  #print 'also adding thread b ', fargs, fep
  thread.sched.addThread(fdefc, fcallc, fblockc, fargs, fep, depends=[ta])

def applyContext(defc, vmap):
  fc=defc.clone()
  for key in vmap.keys():
    value=vmap[key]
    fc[key]=value
  return fc

def arbre_with(thread):
  from arbre import Reference
  from trees import MagicList, MagicMap

  #print 'values', thread.symc['values']
  values=thread.symc['values']
  vtype=values[0]
  if vtype!='literal':
    print 'type error, with values not literal'
    return
  vmap=values[1]
  if vmap.__class__!=MagicMap:
    print 'type error, with vmap not msp'
    return

  f=thread.symc['f'][1]['code']
  print 'f:', f, f
  ftype=f[0]
  if ftype!='func':
    print 'type error, with f not func'
    return
  #print 'fname:', f[1][0], f[1][0]
  fname=f[1][0]
  fargs=f[1][1]
  fdefc=thread.symc[fname]
  fep=fdefc['code']
  fcallc=applyContext(thread.symc, vmap)
  fblockc=blockc
  #print 'fdefc:', fdefc
  #print 'with adding thread f ', fname, fdefc, fcallc, fargs, fep
  thread.sched.addThread(fdefc, fcallc, fblockc, fargs, fep)

def arbre_eval(thread):
  from arbre import Reference
  from trees import MagicList

  block=thread.symc['block'][1]['code']
  blocktype=block[0]
  if blocktype!='func':
    print 'type error, eval block not func'
    return
  fname=block[1][0]
  fargs=block[1][1]
  fdefc=thread.symc[fname]
  fcallc=thread.symc
  fblockc=blockc
  fep=fdefc['code']
  #print 'eval adding thread ', fname, fdefc, fargs, fep
  thread.sched.addThread(fdefc, fcallc, fblockc, fargs, fep)

def arbre_return(thread):
  print 'return:'
  print thread

  value=thread.symc['value']
  print 'returning value:', value
  thread.terminate(value=value)

def when(thread):
  from arbre import Reference
  from trees import MagicList
  #print 'when thread.symc', thread.symc

  test=thread.symc['test']
  print 'test:', test, test
  testtype=test[0]
  if testtype!='literal':
    print 'when only supports literal tests'
    return
  testval=test[1]

  if testval:
    block=thread.symc['block'][1]['code']
    print 'block:', block, block
    blocktype=block[0]
    if blocktype!='func':
      print 'type error, when block not func'
      return
    fname=block[1][0]
    fargs=block[1][1]
    fdefc=thread.symc[fname]
    fcallc=blockc
    fblockc=blockc
    fep=fdefc['code']
    #print 'when adding thread b ', bfname, bdefc, bargs, bep
    thread.sched.addThread(fdefc, fcallc, fblockc, fargs, fep)

def arbre_if(thread):
  from arbre import Reference
  from trees import MagicList
  #print 'when thread.symc', thread.symc

  print 'symc:', thread.symc

  test=thread.symc['test']
  print 'test:', test, test
  testtype=test[0]
  if testtype!='literal':
    print 'when only supports literal tests'
    return
  testval=test[1]

  if testval:
    block=thread.symc['ifBlock'][1]['code']
  else:
    block=thread.symc['elseBlock'][1]['code']

  print 'block:', block
  blocktype=block[0]
  print 'blocktype:', blocktype
  if blocktype!='func':
    print 'type error, when block not func'
    return
  fname=block[1][0]
  fargs=block[1][1]
  frootc=thread.rootc
  fdefc=thread.symc[fname]
  fcallc=thread.blockc
  fblockc=thread.blockc
  fep=fdefc['code']
  thread.chain(frootc, fdefc, fcallc, fblockc, fargs, fep)

def write(thread):
  print thread.symc['s']

def time(thread):
  import time as tm
  thread.terminate(value=['literal', tm.asctime()])
